package cn.touna.jss.modules.third.pengyuan;

import cn.touna.risk.api.enums.SystemErrorCodeEnum;
import cn.touna.jss.common.exception.ResponseException;
import cn.touna.jss.common.factory.ResponseFactory;
import cn.touna.jss.common.properties.disconf.PengyuanProperties;
import cn.touna.jss.common.util.RaderXml;
import cn.touna.jss.common.util.ValidUtil;
import cn.touna.jss.common.webservice.WebServiceUtil;
import cn.touna.jss.modules.adapter.ApiMapping;
import cn.touna.jss.modules.third.pengyuan.entity.CheckCompanyRequest;
import cn.touna.jss.modules.third.pengyuan.entity.PengyuanEducationRequest;
import cn.touna.jss.modules.third.pengyuan.entity.PengyuanRequest;
import cn.touna.jss.modules.third.pengyuan.util.Base64;
import cn.touna.jss.modules.third.pengyuan.util.CompressStringUtil;
import cn.touna.risk.api.domain.Response;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.touna.loan.log.service.TracerContextUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.StringWriter;
import java.util.*;

@Service
public class PengyuanService {

    @Autowired
    private PengyuanProperties config;

    private static final Logger logger = LogManager.getLogger(PengyuanService.class);

    /**
     * 公积金
     *
     * @return
     */
    @ApiMapping(value="pengyuan.accumulationFund",desc="鹏元.深圳市个人公积金信息查询")
    public Response accumulationFund(PengyuanRequest request) {
        Response response = ValidUtil.valid(request);
        if (response != null) {
            return response;
        }

        int queryType = 25228;
        String subreportIDs = "10408";
        int queryReasonID = request.getQueryReasonID();

        Map<String, Object> condParams = new HashMap<>();
        condParams.put("name", request.getName());
        condParams.put("documentNo", request.getIdCard());
        condParams.put("subreportIDs", subreportIDs);
        condParams.put("queryReasonID", queryReasonID);
        condParams.put("refID", getRefId());
        String conditions = null;
        try {
            conditions = buildConditionsXml(queryType, condParams);
        } catch (ResponseException e) {
            return e.getResponse();
        }
        return call(conditions);
    }

    /**
     * 社保
     *
     * @return
     */
    @ApiMapping(value="pengyuan.socialSecurity",desc="鹏元.商业银行社保查询")
    public Response socialSecurity(PengyuanRequest request) {
        int queryType = 25109;
        String subreportIDs = "10403";
        //TODO
        int queryReasonID = request.getQueryReasonID();
        Map<String, Object> condParams = new HashMap<>();
        condParams.put("name", request.getName());
        condParams.put("documentNo", request.getIdCard());
        condParams.put("subreportIDs", subreportIDs);
        condParams.put("queryReasonID", queryReasonID);
        condParams.put("distibuteFlag", "");
        condParams.put("refID", getRefId());
        String conditions = null;
        try {
            conditions = buildConditionsXml(queryType, condParams);
        } catch (ResponseException e) {
            return e.getResponse();
        }
        return call(conditions);
    }

    /**
     * 电话号码发查
     *
     * @return
     */
    @ApiMapping(value="pengyuan.checkCompany",desc="鹏元.电话号码发查")
    public Response reversePhone(CheckCompanyRequest request) {
        Integer queryType = 25129;
        String subreportIDs = "21603";

        int queryReasonID = request.getQueryReasonID();
        Map<String, Object> condParams = new HashMap<>();
        condParams.put("tel", request.getTel());
        condParams.put("subreportIDs", subreportIDs);
        condParams.put("queryReasonID", queryReasonID);
        condParams.put("refID", getRefId());
        String conditions;
        try {
            conditions = buildConditionsXml(queryType, condParams);
        } catch (ResponseException e) {
            return e.getResponse();
        }
        return call(conditions);
    }

    @ApiMapping(value="pengyuan.education",desc="鹏元.学历查询")
    public Response queryEducation(PengyuanEducationRequest request) {
        Integer queryType = 33107;
        String subreportIDs = "14014";
        if (request == null || request.getQueryReasonID() == null
                || StringUtils.isEmpty(request.getName())
                || StringUtils.isEmpty(request.getIdCard())) {
            Response response = new Response().fail(SystemErrorCodeEnum.JSS_PARAM_CHECK_FAILED);
            response.setMsg("参数不合法");
            return response;
        }
        Map<String, Object> condParams = new HashMap<>();
        condParams.put("name", request.getName());
        condParams.put("documentNo", request.getIdCard());
        condParams.put("mobile", request.getMobile());
        condParams.put("subreportIDs", subreportIDs);
        condParams.put("queryReasonID", request.getQueryReasonID());
        condParams.put("refID", getRefId());
        String conditions;
        try {
            conditions = buildConditionsXml(queryType, condParams);
        } catch (ResponseException e) {
            return e.getResponse();
        }
        return call(conditions);
    }


    private Response call(String conditions) {
        if (conditions == null) {
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_SYSTEM_ERROR, "组装参数异常");
        }
        Object[] params = new Object[]{config.getUserId(), config.getPassword(), conditions, "xml"};
        String body = null;
        try {
            body = WebServiceUtil.invokeHttp(config.getWebserviceUrl(), "queryReport", params);
        } catch (Exception e) {
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR, e.getMessage());
        }
        try {
            String jsonStr = RaderXml.xmlToJsonString(body);
            System.out.println(jsonStr);
            JSONObject resObj = JSONObject.parseObject(jsonStr).getJSONObject("result");
            int status = resObj.getInteger("status");
            Response response = null;
            if (1 == status) {
                String returnValue = resObj.getString("returnValue");
                Base64 base64 = new Base64();
                byte[] re = base64.decode(returnValue);
                returnValue = CompressStringUtil.decompress(re);
                logger.info(TracerContextUtil.getTraceId() + " pengyuan result: ");
                logger.info(returnValue);
                String jsonRes = xmlToJsonStringWithAttribute(returnValue);
                resObj = JSONObject.parseObject(jsonRes);
                resObj.put("status", "1");
                response = ResponseFactory.success(resObj);
            } else {
                String code = resObj.getString("errorCode");
                String message = resObj.getString("errorMessage");
                response = ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_FAIL, code + ":" + message, resObj);
            }
            return response;
        } catch (Exception e) {
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_SYSTEM_ERROR, e.getMessage());
        }
    }

    private String buildConditionsXml(int queryType, Map<String, Object> params) throws ResponseException {
        Document doc = DocumentHelper.createDocument();
        Element conditions = doc.addElement("conditions");
        Element condition = conditions.addElement("condition");
        condition.addAttribute("queryType", String.valueOf(queryType));
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            Element item = condition.addElement("item");
            Element name = item.addElement("name");
            name.setText(entry.getKey());

            Element value = item.addElement("value");
            value.setText(String.valueOf(entry.getValue()));
        }
        // 创建输出格式(OutputFormat对象)
        OutputFormat format = OutputFormat.createPrettyPrint();
        try {
            StringWriter stringWriter = new StringWriter();
            // 创建XMLWriter对象
            XMLWriter writer = new XMLWriter(stringWriter, format);
            //设置不自动进行转义
            writer.setEscapeText(true);
            // 生成XML文件
            writer.write(conditions);
            //关闭XMLWriter对象
            writer.close();
            return stringWriter.toString();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            throw new ResponseException(ResponseFactory.fail(SystemErrorCodeEnum.JSS_SYSTEM_ERROR, e.getMessage()));
        }
    }

    private String getRefId() {
        String refID = TracerContextUtil.getTraceId();
        if (refID == null)
            refID = UUID.randomUUID().toString();
        if (refID.length() > 20) {
            refID = refID.substring(0, 20);
        }
        return refID;
    }

    public static String xmlToJsonStringWithAttribute(String xml) throws DocumentException {
        org.dom4j.Document doc = DocumentHelper.parseText(xml);
        org.dom4j.Element rootElement = doc.getRootElement();
        Map<String, Object> map = new HashMap<String, Object>();
        elementToMap(map, rootElement, true);
        return JSON.toJSONString(map);
    }

    /**
     * 在RaderXml.elementToMap做了细微的改动
     *
     * @param resultMap
     * @param element
     * @param useAttr
     */
    private static void elementToMap(Map<String, Object> resultMap,
                                     org.dom4j.Element element, boolean useAttr) {
        String elementName = element.getName();

        @SuppressWarnings("unchecked")
        List<Element> subElements = element.elements();
        Map<String, Object> attrMap = null;

        if (subElements.size() == 0 && element.attributes().size() == 0) {
            // 没有子节点说明当前节点是叶子节点, 可直接取值
            resultMap.put(elementName, element.getText());
            attrMap = resultMap;
        } else {
            //此处改善，把map抽取出来，最后一起加入resultmap中
            Map<String, Object> map = new HashMap<String, Object>();
            for (org.dom4j.Element subElement : subElements) {
                elementToMap(map, subElement, useAttr);
            }
            //判断原来的resulMap中的值是否已经是一个list。如果是，直接抽取出来进行内容添加，如果不是，则进行数组化
            if (resultMap.containsKey(elementName)) {
                if (resultMap.get(elementName) instanceof List) {
                    List list = (List) resultMap.get(elementName);
                    list.add(map);
                    resultMap.put(elementName, list);
                } else {
                    List list = new ArrayList();
                    list.add(resultMap.get(elementName));
                    list.add(map);
                    resultMap.put(elementName, list);
                }
            } else {
                resultMap.put(elementName, map);
            }

            if (subElements.size() == 0) {
                map.put("text", element.getText());
            }
            attrMap = map;
        }

        if (useAttr && attrMap != null) {
            List<Attribute> attrs = element.attributes();
            for (Attribute attr : attrs) {
                attrMap.put(attr.getName(), attr.getValue());
            }
        }
    }
}
